// package: rewords-server-2024
// filename: admin
// author: diogoxiang@gmail.com
// time: 2024/11/12 10:34
// desc: 系统的一些配置. 通常是 key value 的模式 , 可存储多类型数据

package admin

import (
	"context"
	"rewords-server-2024/internal/consts"
	"rewords-server-2024/internal/dao/cmgox"
	"rewords-server-2024/internal/library/ecode"
	"rewords-server-2024/internal/logic/mgx"
	"rewords-server-2024/internal/model/entity"
	"rewords-server-2024/internal/model/input/form"
	"rewords-server-2024/internal/model/input/query_in"
	"rewords-server-2024/internal/service"
	"rewords-server-2024/utility/ufun"
	"rewords-server-2024/utility/ztime"

	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/util/gconv"
	"go.mongodb.org/mongo-driver/bson"

	"github.com/gogf/gf/v2/errors/gcode"
	"github.com/gogf/gf/v2/errors/gerror"

	"rewords-server-2024/api/admin"
)

var ComConfig = new(comConfig)

type comConfig struct{}

func (c *comConfig) QueryList(ctx context.Context, req *admin.ConfListReq) (res *admin.ConfListRes, err error) {

	query, skip, limit, sortFields, _ := query_in.BuildMongoQueryWithPage(req.Conditions, req.OrderFields, req.Page, nil)
	g.Log().Debug(ctx, "MongoDB query conditions:", query)
	g.Log().Debug(ctx, "Skip:", skip, "Limit:", limit)

	result, err := service.Mgx().Find(ctx, consts.CConfig_app, query, nil, skip, limit, sortFields)
	if err != nil {
		return nil, gerror.Wrap(err, "获取数据失败")
	}

	var configs []entity.SysConfig

	if err = gconv.Struct(result, &configs); err != nil {
		return nil, gerror.Wrap(err, "数据转换失败")
	}
	var total int64
	if req.Page.QueryCount {
		// 获取总记录数
		total, err = service.Mgx().CountDocuments(ctx, consts.CConfig_app, query)
		if err != nil {
			return nil, gerror.Wrap(err, "获取总记录数失败")
		}
	}

	res = &admin.ConfListRes{
		Data: ufun.If(len(configs) > 0, configs, []entity.SysConfig{}),
		PageResult: query_in.PageResult{
			Current:  (skip / limit) + 1,
			PageSize: limit,
			Total:    total,
			Pages:    (total + limit - 1) / limit,
			HasNext:  (skip + limit) < total,
		},
	}

	return res, nil
}
func (c *comConfig) QueryInfo(ctx context.Context, req *admin.ConfInfoReq) (res *admin.ConfInfoRes, err error) {
	qBuilder := cmgox.NewConditionBuilder()

	qSelect := qBuilder.AddOptionalCondition("id", "$eq", req.Id).
		AddOptionalCondition("key", "$eq", req.Key).
		AddOptionalCondition("group", "$eq", req.Group).
		AddOptionalCondition("name", "$eq", req.Name).
		Build()

	result, err := service.Mgx().FindOne(ctx,
		consts.CConfig_app,
		qSelect,
		nil,
	)
	if err != nil {
		return nil, gerror.NewCode(gcode.CodeNotImplemented)
	}
	var entity entity.SysConfig
	if err = gconv.Struct(result, &entity); err != nil {
		return nil, gerror.Wrap(err, "数据转换失败")
	}
	return &admin.ConfInfoRes{
		SysConfig: entity,
	}, nil

}

func (c *comConfig) Add(ctx context.Context, req *admin.ConfAddReq) (res *admin.ConfAddRes, err error) {

	Doc := &entity.SysConfig{
		Id:    req.Id,
		Key:   req.Key,
		Name:  req.Name,
		Value: req.Value,
		Group: req.Group,
		//Type:         req.Type,
		DefaultValue: req.DefaultValue,
		Sort:         req.Sort,
		IsDefault:    req.IsDefault,
		Status:       req.Status,
		Tip:          req.Tip,
		//PublicTime:   req.PublicTime,
	}
	// 后续自增都 用 集合name
	id, err := mgx.GetAutoInc(consts.CConfig_app)

	if err != nil {
		g.Log().Error(ctx, "Add error:", err)
		return nil, gerror.NewCode(ecode.InvalidParams)
	}
	Doc.Id = int64(id)
	Doc.SetTimeValue(0)
	Doc.SetTimeValue(1)

	err = service.Mgx().InsertOne(ctx, consts.CConfig_app, Doc)

	if err != nil {
		g.Log().Error(ctx, "Insert error:", err)
		return nil, gerror.NewCode(ecode.InvalidParams)
	}

	return &admin.ConfAddRes{
		Id: Doc.Id,
	}, nil
}

func (c *comConfig) Update(ctx context.Context, req *admin.ConfUpdateReq) (res *admin.ConfUpdateRes, err error) {
	updateDoc := form.NewBuilder().
		SetIfNotEmpty("key", req.Key).
		SetIfNotEmpty("name", req.Name).
		SetIfNotEmpty("value", req.Value).
		SetIfNotEmpty("group", req.Group).
		SetIfNotEmpty("type", req.Type).
		SetIfNotEmpty("default_value", req.DefaultValue).
		SetIfNotEmpty("sort", req.Sort).
		SetIfNotEmpty("is_default", req.IsDefault).
		SetIfNotEmpty("status", req.Status).
		SetIfNotEmpty("tip", req.Tip).
		Set("updated_at", ztime.GetLocalTime()).
		Build()

	result, err := service.Mgx().UpdateOne(ctx,
		consts.CConfig_app,
		bson.M{"id": req.Id},
		bson.M{"$set": updateDoc},
	)
	if err != nil {
		g.Log().Error(ctx, "Update error:", err)
		return nil, gerror.NewCode(ecode.InvalidParams)
	}

	if result.MatchedCount == 0 {
		return nil, gerror.NewCode(ecode.DataNotFound)
	}

	return &admin.ConfUpdateRes{}, nil
}

func (c *comConfig) BatchUpdate(ctx context.Context, req *admin.ConfBatchUpdateReq) (res *admin.ConfBatchUpdateRes, err error) {
	updatedIds := make([]int64, 0)

	for _, item := range req.Rows {
		// 使用类型断言来获取 map 中的值
		id := gconv.Int64(item["id"])
		status, ok := item["status"].(string)
		if !ok {
			g.Log().Errorf(ctx, "Invalid status format in row: %v", item)
			continue
		}

		updateDoc := form.NewBuilder().
			SetIfNotEmpty("status", status).
			Set("updated_at", ztime.GetLocalTime()).
			Build()

		result, err := service.Mgx().UpdateOne(ctx,
			consts.CConfig_app,
			bson.M{"id": id},
			bson.M{"$set": updateDoc},
		)

		if err != nil {
			g.Log().Errorf(ctx, "Failed to update menu %d: %v", id, err)
			continue
		}

		if result.MatchedCount > 0 {
			updatedIds = append(updatedIds, id)
		}
	}

	return &admin.ConfBatchUpdateRes{Rows: updatedIds}, nil
}

func (c *comConfig) DeleteID(ctx context.Context, req *admin.ConfDeleteReq) (res *admin.ConfDeleteRes, err error) {
	updateDoc := form.NewBuilder().
		Set("deleted_at", ztime.GetLocalTime()).
		Build()

	result, err := service.Mgx().UpdateOne(ctx,
		consts.CConfig_app,
		bson.M{"id": req.Id},
		bson.M{"$set": updateDoc},
	)

	if err != nil {
		g.Log().Error(ctx, "Update error:", err)
		return nil, gerror.NewCode(ecode.InvalidParams)
	}

	if result.MatchedCount == 0 {
		return nil, gerror.NewCode(ecode.DataNotFound)
	}

	return &admin.ConfDeleteRes{}, nil
}
